import os
import matplotlib.font_manager as fm
from typing import List, Optional
import pandas as pd

import time
from typing import Optional

def record_time(name):
    def decorator(func):
        def decorated(*args, **kwargs):
            with Timer(name) as timer:
                func(*args, **kwargs)
            print(f"{timer.name}耗时:{timer.duration}s")
        return decorated
    return decorator
    
    return decorated

class Timer:
    def __init__(self, name: str = "Timer"):
        self.name = name
        self.start_time: Optional[float] = None
        self.end_time: Optional[float] = None
        self.duration: Optional[float] = None

    def __enter__(self):
        self.start_time = time.time()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end_time = time.time()
        self.duration = self.end_time - self.start_time
        return False  # 允许异常传播

    def get_duration(self) -> float:
        if self.duration is None:
            raise RuntimeError("Timer has not been run")
        return self.duration


def ensure_dir(path):
    dirname = os.path.dirname(path)
    os.makedirs(dirname, exist_ok=True)
    return path

def get_font(font_candidates: List[str] = None) -> Optional[str]:
    """
    获取系统支持的优先中文字体
    
    参数:
        font_candidates: 自定义字体优先级列表，默认包含常见中文字体
        
    返回:
        str: 第一个可用的字体名称，若无可用字体返回None
    """
    # 默认候选字体列表（按优先级排序）
    default_candidates = [
        'WenQuanYi Micro Hei',
        'Microsoft YaHei',    # Windows
        'SimHei',             # Windows/Linux
        'WenQuanYi Micro Hei',# Linux (文泉驿微米黑)
        'Noto Sans CJK SC',   # 开源字体
        'Source Han Sans SC', # Adobe开源字体
        'DejaVu Sans'         # 调试信息中存在的字体
    ]
    candidates = font_candidates if font_candidates else default_candidates
    
    # 获取系统所有字体名称（小写形式）
    system_fonts = [f.name.lower() for f in fm.fontManager.ttflist]
    
    # 查找第一个可用的候选字体
    for font in candidates:
        if font.lower() in system_fonts:
            return font
    
    # 二次检查字体文件路径（应对名称不一致的情况）
    system_font_files = [f.lower() for f in fm.findSystemFonts()]
    font_file_patterns = [
        'msyh',     # 微软雅黑文件名特征
        'simhei',   # 黑体
        'stheit',   # 华文黑体
        'wqy-zenhei' # 文泉驿
    ]
    
    for pattern in font_file_patterns:
        if any(pattern in f for f in system_font_files):
            return next(f for f in candidates if pattern in f.lower())
    
    return None

def _preprocess_dates(df, date_col):
    """日期预处理（复用您的异常过滤逻辑）[1,6,7](@ref)"""
    df = df.copy()
    df[date_col] = pd.to_datetime(df[date_col], errors='coerce')
    valid_dates = df[date_col].between('2019-01-01', '2023-12-31')
    return df[valid_dates]

def _set_dynamic_axis(ax, dates):
    """动态日期轴设置（复用您的季度/月度切换逻辑）[1,3,14](@ref)"""
    date_span = (dates.max() - dates.min()).days
    if date_span > 365:
        ax.xaxis.set_major_locator(mdates.MonthLocator(interval=3))
        ax.xaxis.set_major_formatter(lambda x,_: f"{mdates.num2date(x).year}-Q{(mdates.num2date(x).month-1)//3+1}")
    else:
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.xticks(rotation=45, ha='right', fontsize=10)

def _ensure_dir(savedir):
    """创建保存目录（复用您的目录处理逻辑）"""
    if not os.path.exists(savedir):
        os.makedirs(savedir)

def _validate_columns(df, required_cols):
    """列存在性校验（参考网页1的错误预防建议）"""
    missing_cols = [col for col in required_cols if col not in df.columns]
    if missing_cols:
        raise KeyError(f"缺失必要字段: {missing_cols}")